package com.example.demo.base.config.auth;


import cn.hutool.core.collection.CollectionUtil;
import com.example.demo.base.login.dto.UserCache;
import com.example.demo.common.BusinessStateCode;
import com.example.demo.constants.RedisKey;
import com.example.demo.dto.ResponseDto;
import com.example.demo.enums.UserIdentifyEnum;
import com.example.demo.init.ApplicationContextCache;
import com.example.demo.utils.RedisUtil;
import com.google.common.base.Joiner;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.HandlerMethod;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.List;

public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    Gson gson;

    @Value("${login.expire}")
    private Long LOGIN_REDIS_EXPIRE_TIME;

    private AntPathMatcher pathMatcher = new AntPathMatcher();
//
//    @Autowired
//    TokenUtils tokenUtils;

  /*  @Resource
    private RedisUtil redisUtil;*/

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
        RedisUtil redisUtil = ApplicationContextCache.getApplicationContext().getBean(RedisUtil.class);
        String token = request.getHeader("token");
        Gson gson1 = new Gson();
        if (checkLogin(token)) {
            //获取用户身份信息
            String infoString = redisUtil.getValue(token);

            UserCache userCache = gson1.fromJson(infoString, new TypeToken<UserCache>() {
            }.getType());
            UserInfoShareHolder.setUserInfo(userCache);

            if (!UserIdentifyEnum.superAdmin.getIdentify().equals(userCache.getUser().getIdentify())){
                // 校验系统是否开启
                if (redisUtil.existKey(RedisKey.SYS_SWITCH)){
                    String value = redisUtil.getValue(RedisKey.SYS_SWITCH);
                    if ("0".equals(value)){
                        response.getOutputStream().write(gson1.toJson(new ResponseDto<String>().buildFailResponse(BusinessStateCode.SYS_OPEN_OR_CLOSE)).getBytes());
                        return false;
                    }
                }else {
                    response.getOutputStream().write(gson1.toJson(new ResponseDto<String>().buildFailResponse(BusinessStateCode.SYS_OPEN_OR_CLOSE)).getBytes());
                    return false;
                }
            }

            // 权限校验

            if (StringUtils.isEmpty(userCache.getUser().getRole())){
                response.getOutputStream().write(gson1.toJson(new ResponseDto<String>().buildFailResponse(BusinessStateCode.NO_PERMISSION)).getBytes());
                return false;
            }
            List<String> keyOfList = redisUtil.getKeyOfList(RedisKey.REDIS_PERMISSION_BACK_URL_SET.concat(String.valueOf(userCache.getUser().getRole())));
//            String realUrl = getRealUrl(handler, request.getServletPath());
            if (checkAuth(request,keyOfList)) {
                redisUtil.setexpire(token,1500000L);
            } else {
                response.getOutputStream().write(gson1.toJson(new ResponseDto<String>().buildFailResponse(BusinessStateCode.NO_PERMISSION)).getBytes());
                return false;
            }
            return true;

        } else {
            response.getOutputStream().write(gson1.toJson(new ResponseDto<String>().buildFailResponse(BusinessStateCode.LOGIN_EXPIR)).getBytes());
            return false;
        }

//        https://blog.csdn.net/qq_42764468/article/details/127718048
    }
//
//    /**
//     * 校验用户访问权限
//     *
//     * @param request
//     * @return
//     * @Author Meloa
//     */
//
    private boolean checkAuth(String realUrl,List<String> strings) {
//        String aptway = request.getServletPath();
//
//        String requestURI = request.getRequestURI();
//        String contextPath = request.getContextPath();
//        String servletPath = requestURI.substring(contextPath.length());

        //判断是否有权限做操作
        if (!CollectionUtil.isEmpty(strings)){
            if (strings.contains(realUrl)){
                return true;
            }
        }

        return false;
    }


    private boolean checkAuth(HttpServletRequest request,List<String> strings) {
        String aptway = request.getServletPath();
//        String[] aptways = aptway.split("/");

        String requestURI = request.getRequestURI();
        String contextPath = request.getContextPath();
        String servletPath = requestURI.substring(contextPath.length());

        //判断是否有权限做操作
        for (String allowedPath : strings) {
            if (pathMatcher.match(allowedPath, aptway)) {
                return true; // 放行
            }
        }
        /*if (!CollectionUtil.isEmpty(strings)){
            if (strings.contains(aptway)){
                return true;
            }
        }*/

        return false;
    }
//
//
    /**
     * 校验用户是否登陆
     *
     *
     * @return
     * @Author Meloa
     */
    private boolean checkLogin(String token) {
        RedisUtil redisUtil = ApplicationContextCache.getApplicationContext().getBean(RedisUtil.class);
        if (token == null) {
            return false;
        }
        return redisUtil.existKey(token);
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserInfoShareHolder.remove();
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    private String getRealUrl(Object handler,String url){
        Annotation[][] parameterAnnotations = ((HandlerMethod) handler).getMethod().getParameterAnnotations();
        int i = 0;
        for (Annotation[] annotations : parameterAnnotations) {
            for (Annotation annotation : annotations) {
                if(annotation instanceof PathVariable){
                    i++;
                    break;
                }
            }
        }
        if (i == 0){
            return url;
        }
        List<String> split = Arrays.asList(url.split("\\/"));
        List<String> subList = split.subList(0, split.size() - i);
        String join = Joiner.on("/").join(subList);
        return join;
    }
//
//
}
